package com.github.xzb617.client.config.refresher;

import com.github.xzb617.client.base.props.ClientProperties;
import com.github.xzb617.client.base.props.ClientPropertiesFactory;
import com.github.xzb617.client.base.props.BaseProperties;
import com.github.xzb617.client.base.props.BasePropertiesFactory;
import com.github.xzb617.client.config.props.ClientConfigProperties;
import com.github.xzb617.client.config.props.ClientConfigPropertiesFactory;
import com.github.xzb617.client.config.serv.ConfigService;
import com.github.xzb617.client.config.serv.ConfigServiceFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MutablePropertySources;

import java.util.HashMap;
import java.util.Map;

public class ClientConfigEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {

    private final static Logger LOGGER = LoggerFactory.getLogger(ClientConfigEnvironmentPostProcessor.class);


    @Override
    public void postProcessEnvironment(ConfigurableEnvironment configurableEnvironment, SpringApplication application) {
        MutablePropertySources propertySources = configurableEnvironment.getPropertySources();
        if (!RefresherCache.isSameBatch())
        {
            // bootstrap
            Map config = this.getConfigToProperties(configurableEnvironment, propertySources);
            if (config != null) {
                // 处理配置
                this.handleCappuccinoPropertySources(propertySources, config);
            }
            // 添加标识，即缓存同一批次的结果（重复请求了两次）
            RefresherCache.markSameBatch(config);
        }
        else
        {
            // application
            Map config = RefresherCache.getCache();
            // 处理配置
            if (config != null) {
                this.handleCappuccinoPropertySources(propertySources, config);
            }
        }

        // 将ConfigurationPropertySources的优先级重置到最优先位置（适配Spring环境后置处理器编排逻辑）
        ConfigurationPropertySources.attach(configurableEnvironment);
    }

    @Override
    public int getOrder() {
        return LOWEST_PRECEDENCE;
    }

    private HashMap getConfigToProperties(ConfigurableEnvironment configurableEnvironment, MutablePropertySources propertySources) {
        // 解析 ClientProperties
        ClientProperties clientProperties = ClientPropertiesFactory.load(configurableEnvironment, propertySources);
        BaseProperties baseProperties = BasePropertiesFactory.load(configurableEnvironment, propertySources);
        ClientConfigProperties configProperties = ClientConfigPropertiesFactory.load(configurableEnvironment, propertySources);
        // 生成 ConfigService
        ConfigService configService = ConfigServiceFactory.getInstance(clientProperties, baseProperties, configProperties);
        // 查询
        HashMap configMap = (HashMap) configService.getConfigFromServer();
        return configMap;
    }


    private void handleCappuccinoPropertySources(MutablePropertySources propertySources, Map properties) {
        // 解析 PropertySource
        ClientPropertySource cappuccinoPropertySource = new ClientPropertySource(properties);
        String propertySourceName = cappuccinoPropertySource.getName();
        if (propertySources.get(propertySourceName) != null) {
            propertySources.replace(propertySourceName, cappuccinoPropertySource);
        } else {
            propertySources.addFirst(cappuccinoPropertySource);
        }
        // 打印日志
        LOGGER.info("Successfully loaded the configuration file from the goalkeeper server, includes {} configuration items.", properties.keySet().size());
    }

}
